"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : GUC_ErrorLog
Case Name   : 测试log_duration为on时的日志记录
Create At   : 2022/06/06
Owner       : opentestcase019
Description :
    1.log_statement=none时,修改参数log_duration=on
    2.执行小于2s的语句，查看pg_log日志文件中是否记录sql语句及耗时
    3.执行大于2s的语句，查看pg_log日志文件中是否记录sql语句及耗时
    4.设置参数log_statement=all
    5.执行小于2s的语句，查看pg_log日志文件中是否记录sql语句及耗时
    6.执行大于2s的语句，查看pg_log日志文件中是否记录sql语句及耗时
    7.恢复参数
Expect      :
    1.修改成功
    2.日志中不记录statement信息和小于2s的语句耗时
    3.日志中记录大于2s的语句耗时，且log_duration会记录statement信息
    4.设置成功
    5.日志中记录statement信息，不记录小于2s的语句耗时
    6.日志中记录statement信息，log_duration不会重复记录statement信息
    7.恢复成功
History     :
    Modified by opentestcase019 2022/7/6:修改日志打印语句，修改断言
    Modified by opentestcase019 2022/7/19:修改日志打印语句
    Modified by opentestcase019 2022/7/26:增加if判断，规避用例执行时间为凌晨前后生成两个日志文件的情况
    Modified by opentestcase019 2022/8/02:修改正则表达式
"""
import os
import re
import unittest
from yat.test import Node
from yat.test import macro
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Logger import Logger
from testcase.utils.Constant import Constant


class ErrorLog(unittest.TestCase):
    def setUp(self):
        self.logger = Logger()
        self.logger.info(f"-----{os.path.basename(__file__)} start-----")
        self.primary_node = Node('PrimaryDbUser')
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.common = Common()
        self.constant = Constant()
        self.dir_new = os.path.join(macro.PG_LOG_PATH,
                                    'pg_log_guc_errorlog_case0107')
        self.log_min_duration = 'log_min_duration_statement'
        self.log_min_default = self.common.show_param(self.log_min_duration)
        self.log_dir = 'log_directory'
        self.log_dir_default = self.common.show_param(self.log_dir)
        self.log_statement = 'log_statement'
        self.log_stat_default = self.common.show_param(self.log_statement)
        self.log_duration = 'log_duration'
        self.log_duration_default = self.common.show_param(self.log_duration)

    def test_error_log(self):
        text = '-----前置条件:参数log_min_duration_statement = 2s,' \
               'log_directory设置新的路径;expect:设置成功-----'
        self.logger.info(text)
        if '2s' != self.log_min_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_min_duration}=2s')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_min_duration)
        self.assertEquals(show_msg, '2s', '执行失败' + text)

        if self.dir_new != self.log_dir_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_dir}=\'{self.dir_new}\'')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_dir)
        self.assertEquals(show_msg, self.dir_new, '执行失败' + text)

        text = '-----step1:log_statement=none时,修改参数log_duration=on;' \
               'expect:修改成功-----'
        self.logger.info(text)
        if 'none' != self.log_stat_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_statement}=none')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_statement)
        self.assertEquals(show_msg, 'none', '执行失败' + text)
        if 'on' != self.log_duration_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_duration}=on')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_duration)
        self.assertEquals(show_msg, 'on', '执行失败' + text)

        text = '-----step2:执行小于2s的语句，查看pg_log日志文件是否记录sql语句' \
               '及耗时;expect:日志中不记录statement信息和小于2s的语句耗时-----'
        self.logger.info(text)
        sql_cmd = f"select now(),pg_sleep(1);"
        self.logger.info(sql_cmd)
        sql_msg = self.primary_sh.execut_db_sql(sql_cmd)
        self.logger.info(sql_msg)
        self.assertIn('(1 row)', sql_msg, '执行失败:' + text)
        self.logger.info('-------查看日志文件内容-------')
        shell_cmd = f'''ls -l {self.dir_new} '''
        self.logger.info(shell_cmd)
        shell_msg = self.primary_node.sh(shell_cmd).result()
        self.logger.info(shell_msg)
        logfile = os.path.join(self.dir_new,
                               shell_msg.splitlines()[-1].split()[-1])
        self.logger.info(logfile)
        cat_cmd = f"cat {logfile} "
        self.logger.info(cat_cmd)
        cat_msg = self.primary_node.sh(cat_cmd).result()
        self.logger.info(cat_msg)
        self.assertNotIn('LOG:  statement: select now(),pg_sleep(1);'
                         and 'LOG:  duration', cat_msg, '执行失败:' + text)

        text = '-----step3:执行大于于2s的语句，查看pg_log日志文件是否记录sql语句' \
               '及耗时;expect:日志中记录大于2s的语句耗时，且log_duration会记录statement信息-----'
        self.logger.info(text)
        sql_cmd = f"select now(),pg_sleep(4);"
        self.logger.info(sql_cmd)
        sql_msg = self.primary_sh.execut_db_sql(sql_cmd)
        self.logger.info(sql_msg)
        self.assertIn('(1 row)', sql_msg, '执行失败:' + text)
        self.logger.info('-------查看日志文件内容-------')
        shell_cmd = f"ls -l {self.dir_new} "
        self.logger.info(shell_cmd)
        shell_msg = self.primary_node.sh(shell_cmd).result()
        self.logger.info(shell_msg)
        log_count = shell_msg.count('.log')
        self.logger.info(log_count)
        if log_count == 1:
            cat_cmd = f"cat {logfile} "
            self.logger.info(cat_cmd)
            cat_msg = self.primary_node.sh(cat_cmd).result()
            self.logger.info(cat_msg)
            expect_3 = "LOG:  duration: 4\\d+(\\.\\d+) ms queryid \\d+ unique" \
                       " id \\d+ statement: select now\\(\\),pg_sleep\\(4\\);"
            search_res = re.search(expect_3, cat_msg, re.S)
            self.assertIsNotNone(search_res, '执行失败' + text)
        else:
            logfile_2 = os.path.join(self.dir_new,
                                     shell_msg.splitlines()[-1].split()[-1])
            cat_cmd_1 = f"cat {logfile} "
            self.logger.info(cat_cmd_1)
            cat_msg_1 = self.primary_node.sh(cat_cmd_1).result()
            self.logger.info(cat_msg_1)
            cat_cmd_2 = f"cat {logfile_2}"
            self.logger.info(cat_cmd_2)
            cat_msg_2 = self.primary_node.sh(cat_cmd_2).result()
            self.logger.info(cat_msg_2)
            expect_3 = "LOG:  duration: 4\\d+(\\.\\d+) ms queryid \\d+ unique" \
                       " id \\d+ statement: select now\\(\\),pg_sleep\\(4\\);"
            search_res_1 = re.search(expect_3, cat_msg_1, re.S)
            search_res_2 = re.search(expect_3, cat_msg_2, re.S)
            self.assertIsNotNone(search_res_1 or search_res_2, '执行失败' + text)

        text = '-----step4:设置参数log_statement=all;expect:设置成功-----'
        self.logger.info(text)
        if 'all' != self.log_stat_default:
            result = self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_statement}=all')
            self.assertTrue(result, '执行失败' + text)
        show_msg = self.common.show_param(self.log_statement)
        self.assertEquals(show_msg, 'all', '执行失败' + text)

        text = '-----step5:执行小于2s的语句，查看pg_log日志文件是否记录sql语句' \
               '及耗时;expect:日志中记录statement信息，不记录小于2s的语句耗时-----'
        self.logger.info(text)
        sql_cmd = f"select now(),pg_sleep(1);"
        self.logger.info(sql_cmd)
        sql_msg = self.primary_sh.execut_db_sql(sql_cmd)
        self.logger.info(sql_msg)
        self.assertIn('(1 row)', sql_msg, '执行失败:' + text)
        self.logger.info('-------查看日志文件内容-------')
        shell_cmd = f"ls -l {self.dir_new} "
        self.logger.info(shell_cmd)
        shell_msg = self.primary_node.sh(shell_cmd).result()
        self.logger.info(shell_msg)
        log_count = shell_msg.count('.log')
        self.logger.info(log_count)
        if log_count == 1:
            tail_cmd = f"tail -n 10 {logfile} "
            self.logger.info(tail_cmd)
            tail_msg = self.primary_node.sh(tail_cmd).result()
            self.logger.info(tail_msg)
            self.assertIn('LOG:  statement: select now(),pg_sleep(1);',
                          tail_msg, '执行失败:' + text)
            self.assertNotIn('LOG:  duration', tail_msg, '执行失败:' + text)
        else:
            logfile_2 = os.path.join(self.dir_new,
                                     shell_msg.splitlines()[-1].split()[-1])
            tail_cmd = f"tail -n 20 {logfile} "
            self.logger.info(tail_cmd)
            tail_msg = self.primary_node.sh(tail_cmd).result()
            self.logger.info(tail_msg)
            cat_cmd = f"cat {logfile_2}"
            self.logger.info(cat_cmd)
            cat_msg = self.primary_node.sh(cat_cmd).result()
            self.logger.info(cat_msg)
            assert_1 = 'LOG:  statement: select now(),pg_sleep(1);' in tail_msg
            assert_2 = 'LOG:  statement: select now(),pg_sleep(1);' in cat_msg
            self.assertTrue(assert_1 or assert_2, '执行失败:' + text)
            tail_cmd = f"tail -n 10 {logfile_2} "
            self.logger.info(tail_cmd)
            tail_msg = self.primary_node.sh(tail_cmd).result()
            self.logger.info(tail_msg)
            self.assertNotIn('LOG:  duration', tail_msg, '执行失败:' + text)

        text = '-----step6:执行大于于2s的语句，查看pg_log日志文件' \
               '是否记录sql语句及耗时;expect:日志中记录大于2s的语句耗时，' \
               'log_duration不会重复记录statement信息-----'
        self.logger.info(text)
        sql_cmd = f"select pg_sleep(5);"
        self.logger.info(sql_cmd)
        sql_msg = self.primary_sh.execut_db_sql(sql_cmd)
        self.logger.info(sql_msg)
        self.assertIn('(1 row)', sql_msg, '执行失败:' + text)
        self.logger.info('-------查看日志文件内容-------')
        shell_cmd = f"ls -l {self.dir_new} "
        self.logger.info(shell_cmd)
        shell_msg = self.primary_node.sh(shell_cmd).result()
        self.logger.info(shell_msg)
        log_count = shell_msg.count('.log')
        self.logger.info(log_count)
        if log_count == 1:
            tail_cmd = f"tail -n 25 {logfile} "
            self.logger.info(tail_cmd)
            tail_msg = self.primary_node.sh(tail_cmd).result()
            self.logger.info(tail_msg)
            self.assertIn('LOG:  statement: select pg_sleep(5);',
                          tail_msg, '执行失败:' + text)
            expect_6_1 = "LOG:  duration: 5\\d+(\\.\\d+) ms queryid \\d+ " \
                         "unique id \\d+ statement: select pg_sleep\\(5\\);"
            search_res = re.search(expect_6_1, tail_msg, re.S)
            self.assertIsNone(search_res, '执行失败' + text)
            expect_6_2 = "LOG:  duration: 5\\d+(\\.\\d+) ms, " \
                         "queryid \\d+, unique id \\d+"
            search_res_2 = re.search(expect_6_2, tail_msg, re.S)
            self.assertIsNotNone(search_res_2, '执行失败' + text)
        else:
            logfile_2 = os.path.join(self.dir_new,
                                     shell_msg.splitlines()[-1].split()[-1])
            tail_cmd = f"tail -n 25 {logfile} "
            self.logger.info(tail_cmd)
            tail_msg = self.primary_node.sh(tail_cmd).result()
            self.logger.info(tail_msg)
            cat_cmd = f"cat {logfile_2}"
            self.logger.info(cat_cmd)
            cat_msg = self.primary_node.sh(cat_cmd).result()
            self.logger.info(cat_msg)
            assert_1 = 'LOG:  statement: select pg_sleep(5);' in tail_msg
            assert_2 = 'LOG:  statement: select pg_sleep(5);' in cat_msg
            self.assertTrue(assert_1 or assert_2, '执行失败:' + text)
            expect_6_1 = "LOG:  duration: 5\\d+(\\.\\d+) ms queryid \\d+ " \
                         "unique id \\d+ statement: select pg_sleep\\(5\\);"
            search_res_1 = re.search(expect_6_1, tail_msg, re.S)
            self.assertIsNone(search_res_1, '执行失败' + text)
            search_res_2 = re.search(expect_6_1, cat_msg, re.S)
            self.assertIsNone(search_res_2, '执行失败' + text)
            expect_6_2 = "LOG:  duration: 5\\d+(\\.\\d+) ms, " \
                         "queryid \\d+, unique id \\d+"
            search_res_3 = re.search(expect_6_2, tail_msg, re.S)
            search_res_4 = re.search(expect_6_2, cat_msg, re.S)
            self.assertIsNotNone(search_res_3 or search_res_4, '执行失败' + text)

    def tearDown(self):
        text = '-----step7:恢复参数;expect:恢复成功-----'
        self.logger.info(text)
        log_min_current = self.common.show_param(self.log_min_duration)
        if log_min_current != self.log_min_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_min_duration}=\'{self.log_min_default}\'')
        show_log_min = self.common.show_param(self.log_min_duration)
        
        log_dir_current = self.common.show_param(self.log_dir)
        if log_dir_current != self.log_dir_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_dir}=\'{self.log_dir_default}\'')
        show_log_dir = self.common.show_param(self.log_dir)

        log_stat_current = self.common.show_param(self.log_statement)
        if log_stat_current != self.log_stat_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_statement}=\'{self.log_stat_default}\'')
        show_log_statement = self.common.show_param(self.log_statement)

        log_duration_current = self.common.show_param(self.log_duration)
        if log_duration_current != self.log_duration_default:
            self.primary_sh.execute_gsguc(
                'reload', self.constant.GSGUC_SUCCESS_MSG,
                f'{self.log_duration}=\'{self.log_duration_default}\'')
        show_log_duration = self.common.show_param(self.log_duration)
        self.logger.info('-----断言tearDown-----')
        self.assertEquals(show_log_min, self.log_min_default,
                          '执行失败' + text)
        self.assertEquals(show_log_dir, self.log_dir_default,
                          '执行失败' + text)
        self.assertEquals(show_log_statement, self.log_stat_default,
                          '执行失败' + text)
        self.assertEquals(show_log_duration, self.log_duration_default,
                          '执行失败' + text)
        self.logger.info(f"-----{os.path.basename(__file__)} end-----")
